/* eslint-disable @typescript-eslint/no-explicit-any */
import { nanoid } from "nanoid";
import { useRouter, useSearchParams } from "next/navigation";
import { useCallback, useEffect, useState } from "react";

import { createClient } from "~/lib/supabase/client";

import { useAgentCode } from "./use-agent-code";

const PAGE_SIZE = 500;

export function useThreads() {
  const supabase = createClient();
  const [threads, setThreads] = useState<any[]>([]);
  const [page, setPage] = useState(0);
  const [hasMore, setHasMore] = useState(true);
  const [loading, setLoading] = useState(false);
  const [loadingMore, setLoadingMore] = useState(false);
  const router = useRouter();
  const searchParams = useSearchParams();
  const paramThreadId = searchParams.get("threadId");
  const agentCode = useAgentCode();

  const fetchThreads = useCallback(
    async (currentPage: number) => {
      if (currentPage === 0) {
        setLoading(true);
      } else {
        setLoadingMore(true);
      }

      const from = currentPage * PAGE_SIZE;
      const to = from + PAGE_SIZE - 1;

      const { data } = await supabase
        .from("projects")
        .select("*")
        .eq("is_deleted", false)
        .order("created_at", { ascending: false })
        .range(from, to);

      if (data) {
        setThreads((prevThreads) =>
          currentPage === 0 ? data : [...prevThreads, ...data],
        );
        if (data.length < PAGE_SIZE) {
          setHasMore(false);
        }
      } else {
        setHasMore(false);
      }

      if (currentPage === 0) {
        setLoading(false);
      } else {
        setLoadingMore(false);
      }
    },
    [supabase],
  );

  const newThread = useCallback(() => {
    router.push(`/agents/${agentCode}?threadId=${nanoid()}`);
  }, [agentCode, router]);

  const deleteThread = useCallback(
    async (id: string) => {
      const { error } = await supabase
        .from("projects")
        .update({ is_deleted: true })
        .eq("project_id", id)
        .select();
      if (!error) {
        setThreads((prevThreads) =>
          prevThreads.filter((thread) => thread.project_id !== id),
        );
        if (id === paramThreadId) {
          newThread();
        }
      }
    },
    [supabase, paramThreadId, newThread],
  );

  useEffect(() => {
    const channel = supabase
      .channel("custom-all-channel")
      .on(
        "postgres_changes",
        {
          event: "*",
          schema: "public",
          table: "projects",
        },
        (payload) => {
          console.log("Change received!", payload);
          if (payload.eventType === "UPDATE") {
            if (!payload.new.is_deleted) {
              setThreads((prevThreads) =>
                prevThreads.map((thread) =>
                  thread.project_id === payload.new.project_id
                    ? payload.new
                    : thread,
                ),
              );
            }
          } else if (payload.eventType === "INSERT") {
            setThreads((prevThreads) => [payload.new, ...prevThreads]);
          }
        },
      )
      .subscribe();
    return () => {
      void supabase.removeChannel(channel);
    };
  }, [supabase]);

  const loadMore = () => {
    if (hasMore && !loadingMore) {
      const nextPage = page + 1;
      setPage(nextPage);
      void fetchThreads(nextPage);
    }
  };

  const reload = useCallback(() => {
    setThreads([]);
    setPage(0);
    setHasMore(true);
    void fetchThreads(0);
  }, [fetchThreads]);

  useEffect(() => {
    reload();
  }, [reload]);

  return {
    threads,
    loadMore,
    hasMore,
    reload,
    loading,
    loadingMore,
    deleteThread,
  };
}
